import 'dart:convert' as convert;
import 'bean/beans.dart';
import 'dart:io';
import 'package:http/http.dart' as http;

const headers = {
  "X-Bmob-Application-Id": "ad37e0098b7e446b7b189df036dfcb0b",
  "X-Bmob-REST-API-Key": "5b87b6ff63c1124370f5e40ad7f85b07",
  "Content-Type": "application/json"
};

const host = "https://api2.bmob.cn/1";

test() async {
  var s = Uri.encodeComponent(
      '{"\$relatedTo":{"object":{"__type":"Pointer","className":"classify","objectId":"3nEI444g"},"key":"books"}}');
  var url = 'https://api2.bmob.cn/1/classes/books?where=$s';
  print("url:$url");
  var httpClient = new HttpClient();
  var request = await httpClient.getUrl(Uri.parse(url));
  request.headers.add("X-Bmob-Application-Id", "ad37e0098b7e446b7b189df036dfcb0b");
  request.headers.add("X-Bmob-REST-API-Key", "5b87b6ff63c1124370f5e40ad7f85b07");
  var response = await request.close();
  if (response.statusCode == HttpStatus.ok) {
    var responseBody = await response.transform(convert.utf8.decoder).join();
    print("----responseBody: $responseBody");
    Map map = convert.jsonDecode(responseBody);
    List results = map["results"];
    print("----book length: ${results.length}");
  } else {
    print("statusCode: ${response.statusCode}");
  }
}

Future<String> httpGet(String url) async {
  print("get url:$url");
  var httpClient = new HttpClient();
  var request = await httpClient.getUrl(Uri.parse(url));
  request.headers.add("X-Bmob-Application-Id", "ad37e0098b7e446b7b189df036dfcb0b");
  request.headers.add("X-Bmob-REST-API-Key", "5b87b6ff63c1124370f5e40ad7f85b07");
  var response = await request.close();
  if (response == null) {
    print("response == null");
    return null;
  }
  if (response.statusCode != HttpStatus.ok) {
    print("statusCode: ${response.statusCode}");
    return null;
  }
  var responseBody = await response.transform(convert.utf8.decoder).join();
  return Future(() {
    print("responseBody: $responseBody");
    return responseBody;
  });
}

Future httpPost(String url, {Object body, Map<String, String> header}) async {
  print("post url:$url");
  print("post body:$body");
  var response = await http.post(url, headers: header == null ? headers : header, body: body);
  if (response == null) {
    print("response == null");
    return null;
  }
  print("statusCode: ${response.statusCode}");
//  if (response.statusCode < 200 && response.statusCode > 299) {
//    return null;
//  }
  print("responseBody: ${response.body}");
  return response.body;
}

Future httpPut(String url, {Object body}) async {
  print("put url:$url");
  print("put body:$body");
  var response = await http.put(url, headers: headers, body: body);
  if (response == null) {
    print("response == null");
    return null;
  }
  print("statusCode: ${response.statusCode}");
//  if (response.statusCode < 200 && response.statusCode > 299) {
//    return null;
//  }
  print("responseBody: ${response.body}");
  return response.body;
}

Future httpDelete(String url) async {
  print("delete url:$url");
  var response = await http.delete(url, headers: headers);
  if (response == null) {
    print("response == null");
    return null;
  }
  print("statusCode: ${response.statusCode}");
//  if (response.statusCode < 200 && response.statusCode > 299) {
//    return null;
//  }
  print("responseBody: ${response.body}");
  return response.body;
}

Future<List<HomeBanner>> getHomeBanner() async {
  var url = "$host/classes/homebanner";
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];
  List<HomeBanner> list = [];
  results.forEach((key) {
    Map m = key;
    HomeBanner bean = HomeBanner.fromJson(m);
    list.add(bean);
  });
  return list;
}

Future<List<Classify>> getClassify() async {
  var url = "$host/classes/classify?include=books";
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];

  List<Classify> list = [];
  results.forEach((key) {
    Map m = key;
    Classify bean = Classify.fromJson(m);
    list.add(bean);
  });
  return list;
}

Future<Book> getBook(String bookId) async {
  var url = '$host/classes/books/$bookId';
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];
  return Book.fromJson(map);
}

Future<List<Book>> getBookByClassify(String classifyId) async {
  var s = Uri.encodeComponent(
      '{"\$relatedTo":{"object":{"__type":"Pointer","className":"classify","objectId":"$classifyId"},"key":"books"}}');
  var url = '$host/classes/books?where=$s';
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];

  List<Book> list = [];
  results.forEach((key) {
    Map m = key;
    Book bean = Book.fromJson(m);
    if (bean.recommend == null) {
      bean.recommend = 0;
    }
    list.add(bean);
  });
  list.sort((a, b) {
    return a.recommend.compareTo(b.recommend);
  });
  return list;
}

Future<List<Chapter>> getChapterByBook(Book book) async {
  var where = Uri.encodeComponent(
      '{"\$relatedTo":{"object":{"__type":"Pointer","className":"books","objectId":"${book.objectId}"},"key":"chapters"}}');
  var url = '$host/classes/chapters?where=$where';
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];

  List<Chapter> list = [];
  results.forEach((key) {
    Map m = key;
    Chapter bean = Chapter.fromJson(m);
    list.add(bean);
  });
  return list;
}

Future<List<Book>> getCollectBooks(String userId) async {
  var where = Uri.encodeComponent(
      '{"\$relatedTo":{"object":{"__type":"Pointer","className":"user","objectId":"$userId"},"key":"collect"}}');
  var url = '$host/classes/books?where=$where';
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];

  List<Book> list = [];
  results.forEach((key) {
    Map m = key;
    Book bean = Book.fromJson(m);
    list.add(bean);
  });
  return list;
}

Future<User> getUserByPhoneNumber(String phoneNumber) async {
  var where = Uri.encodeComponent('{"phoneNumber":"$phoneNumber"}');
  var url = "$host/classes/user?where=$where";
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];
  if (results == null || results.length == 0) {
    return null;
  }
  return User.fromJson(results[0]);
}

Future registerWithPhoneNumber(String phoneNumber) async {
  var user = User();
  user.phoneNumber = phoneNumber;
  var url = "$host/classes/user";
  try {
    var responseBody = await httpPost(url, body: convert.jsonEncode(user.toRegisterJson()));
    return UserCreate.fromJson(convert.jsonDecode(responseBody));
  } catch (e) {
    print("registerWithPhoneNumber exception: $e");
    return null;
  }
}

Future updateUser(String userId, Map newValue) async {
  var url = "$host/classes/user/$userId";
  try {
    var responseBody = await httpPut(url, body: convert.jsonEncode(newValue));
    var map = convert.jsonDecode(responseBody);
    if (map["updatedAt"] != null) {
      return true;
    }
  } catch (e) {
    print("updateUser exception: $e");
  }
  return false;
}

Future requestSmsCode(String phoneNumber) async {
  var url = "$host/requestSmsCode";
  var responseBody = await httpPost(url, body: '{"mobilePhoneNumber": "$phoneNumber", "template": "登录注册"}');
  return convert.jsonDecode(responseBody);
}

Future verifySmsCode(String phoneNumber, String smsCode) async {
  var url = "$host/verifySmsCode/$smsCode";
  var responseBody = await httpPost(url, body: '{"mobilePhoneNumber": "$phoneNumber"}');
  return convert.jsonDecode(responseBody);
}

Future addCollect(String userId, String bookId) async {
  var url = '$host/classes/user/$userId';
  var responseBody = await httpPut(url,
      body:
          '{"collect":{"__op":"AddRelation","objects":[{"__type":"Pointer","className":"books","objectId":"$bookId"}]}}');
  return convert.jsonDecode(responseBody);
}

Future removeCollect(String userId, String bookId) async {
  var url = '$host/classes/user/$userId';
  var responseBody = await httpPut(url,
      body:
          '{"collect":{"__op":"RemoveRelation","objects":[{"__type":"Pointer","className":"books","objectId":"$bookId"}]}}');
  return convert.jsonDecode(responseBody);
}

Future<int> getBookChapterCount(String bookId) async {
  var where = Uri.encodeComponent(
      '{"\$relatedTo":{"object":{"__type":"Pointer","className":"books","objectId":"$bookId"},"key":"chapters"}}');
  var url = '$host/classes/chapters?where=$where&count=1&limit=0';
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  int count = map["count"];
  return count;
}

Future<int> getBookPlayCount(String bookId) async {
  var where = Uri.encodeComponent(
      '{"\$relatedTo":{"object":{"__type":"Pointer","className":"books","objectId":"$bookId"},"key":"chapters"}}');
  var url = '$host/classes/chapters?where=$where&sum=playcount';
  var responseBody = await httpGet(url);
  Map map = convert.jsonDecode(responseBody);
  List results = map["results"];
  if (results != null && results.length > 0) {
    return results[0]["_sumPlaycount"];
  }
  return 0;
}

Future addBooksForClassify(String classifyId, String bookId) async {
  var url = '$host/classes/classify/$classifyId';
  var responseBody = await httpPut(url,
      body:
          '{"books":{"__op":"AddRelation","objects":[{"__type":"Pointer","className":"books","objectId":"$bookId"}]}}');
  return convert.jsonDecode(responseBody);
}

Future uploadHeadImg(File file, String fileName) async {
  var url = 'https://api2.bmob.cn/2/files/$fileName';
  List<int> bytes = await file.readAsBytes();
  Map<String, String> header = {};
  for (String key in headers.keys) {
    header[key] = headers[key];
  }
  header["Content-Type"] = "image/jpeg";
  var responseBody = await httpPost(url, body: bytes, header: header);
  return convert.jsonDecode(responseBody);
}

Future deleteHeadImg(User user) async {
  if (user == null || user.headUrl == null || user.headCdn == null) {
    return true;
  }
  Uri uri = Uri.parse(user.headUrl);
  var url = 'https://api2.bmob.cn/2/files/${user.headCdn}${uri.path}';
  var responseBody = await httpDelete(url);
  var map = convert.jsonDecode(responseBody);
  if (map != null && map["msg"] == "ok") {
    return true;
  }
  return false;
}
